<template>
  <input type="text" v-model="firstName" />
  <br />
  <input type="text" v-model="lastName" />
  <br />
  <input type="text" v-model="name" />
  <br />
  <table border style="width: 500px; text-align: center">
    <thead>
      <th>name</th>
      <th>number</th>
      <th>price</th>
      <th>delete</th>
    </thead>
    <tbody>
      <tr v-for="(item, index) in data" :key="item.id">
        <td>{{ item.name }}</td>
        <td>
          <button @click="addAndSub(item, false, index)">-1</button>
          {{ item.num }}
          <button @click="addAndSub(item, true, index)">+1</button>
        </td>
        <td>{{ item.price }}</td>
        <td><button @click="del(index)">delete</button></td>
      </tr>
    </tbody>
    <tfoot>
      <td></td>
      <td></td>
      <td></td>
      <td>total {{ total }}</td>
    </tfoot>
  </table>
</template>
<script setup lang="ts">
import { computed, reactive } from '@vue/reactivity'
import { ref } from 'vue'

// computed 计算属性，参数可以为回调或对象
// 参数为回调时，仅定义计算属性的 get 行为，回调的返回值为计算属性的值，实质为单向计算
// 即相关数据变化，计算属性随之变化，常用于非表单元素的计算属性
// const computedVal = computed(() => {
//   返回值为若干个相关值 val 进行特定操作后的值，且当相关值 val 变化时，会重新计算
//   return fun(...val)
// })
// 参数为对象时，在对象中定义 get set 行为，该对象为计算属性，实质为双向计算
// 即相关数据变化，计算属性随之变化，计算属性变化，相关数据变化，常用于表单元素的计算属性
// const computedVal = computed(() => {
//   修改计算属性后，触发 set 行为，将计算属性的新值与相关值进行特定操作
//   set(newVal) {
//     fun(...val, newVal )
//   },
//   get() {
//     return fun(...val)
//   },
// })
// 计算属性可以根据相关数据变化自动计算其值，并将新值更新渲染到页面
// 不必每次在修改相关值时，调用方法计算出特定值

const firstName = ref('')
const lastName = ref('')
// 以回调函数的形式定义计算属性，只定义了 get 行为
// const name = computed(() => {
//   return firstName.value + '_' + lastName.value
// })
// 以包含 set get 方法形式定义计算属性，设置其获取以及修改的行为
const name = computed({
  get() {
    return firstName.value + '_' + lastName.value
  },
  set(val) {
    const names = val.trim().split('_')
    firstName.value = names[0]
    lastName.value = names[1]
  },
})

// 定义商品的接口
interface Goods {
  name: string
  num: number
  price: number
  id: number
}
// 定义 data 存储商品数组
const data = reactive<Goods[]>([
  { name: '衣服', num: 1, price: 100, id: 0 },
  { name: '裤子', num: 1, price: 200, id: 1 },
  { name: '帽子', num: 1, price: 300, id: 2 },
  { name: '鞋子', num: 1, price: 400, id: 3 },
])
// 定义商品数量 +1 -1 操作
const addAndSub = (item: Goods, flag: boolean, index: number): void => {
  if (item.num > 1 && !flag) {
    item.num--
  }
  if (item.num === 1 && !flag) {
    del(index)
  }
  if (item.num < 99 && flag) {
    item.num++
  }
}
// 定义删除商品操作
const del = (index: number) => {
  data.splice(index, 1)
}
// 定义计算属性 total 即当计算属性相关的响应式数据变化时，其计算属性会重新计算并渲染到页面
// 采用计算属性，可以减少方法的调用，即不用每次修改相关值操作时，均调用一次方法
const total = computed(() => {
  return data.reduce((i: number, item: Goods): number => {
    return (i += item.num * item.price)
  }, 0)
})
</script>
<style scoped></style>
